use cassie_core::config::config::ApplicationConfig;
use cassie_core::fundation::{AppContext, ApplicationContext};

use handlebars::{to_json, Handlebars};

use std::fs::File;
use std::thread;
use walkdir::WalkDir;
/*
REQUEST_CHANNEL主要用于 web 默认路由不存在
向jsruntime 发送request使用
*/

//初始化脚本引擎
pub async fn init_engine() {
  build_defcode();
  let build = thread::Builder::new().name(format!("js-engine"));
  let _ = build.spawn(|| {

  });
}

fn get_config() -> Option<ApplicationConfig> {
  let config_ref = ApplicationContext::get_service::<ApplicationConfig>();
  match config_ref {
    None => None,
    Some(config_ref) => {
      let cof = config_ref.lock().unwrap();
      Some(cof.clone())
    }
  }
}

fn build_defcode() {
  let (controllers, services) = build_resource_path();
  let mut handlebars = Handlebars::new();
  let mut data = Map::new();
  data.insert("controllers".to_string(), to_json(&controllers));
  data.insert("services".to_string(), to_json(&services));
  handlebars.register_template_file("template", "./template/def.hbs").unwrap();
  let mut f = File::create("./resource/def.ts").unwrap();
  handlebars.render_to_write("template", &data, &mut f).unwrap();
}
pub fn build_resource_path() -> (Vec<Item>, Vec<Item>) {
  use std::path::Path;
  let mut controllers = Vec::new();
  let mut services = Vec::new();
  for entry in WalkDir::new("./resource").follow_links(true).into_iter().filter_map(Result::ok) {
    let path = entry.path();
    if path.extension().map_or(false, |ext| ext == "ts") {
      let is_service = path.to_str().map_or(false, |p| p.contains("service"));
      let is_controller = path.to_str().map_or(false, |p| p.contains("controller"));
      if is_service || is_controller {
        let mut path_vec: Vec<_> = path.components().map(|comp| comp.as_os_str().to_str().unwrap()).collect();
        let new = ["."];
        let _: Vec<_> = path_vec.splice(0..2, new).collect();
        let fp = path_vec.join("/");
        let f_name = path.file_stem().unwrap().to_str().unwrap();
        if is_controller {
          controllers.push(Item {
            name: f_name.to_string(),
            path: fp,
          });
        } else {
          services.push(Item {
            name: f_name.to_string(),
            path: fp,
          });
        }
      }
    }
  }
  (controllers, services)
}
use serde::Serialize;
use serde_json::{json, Map};
use url::Url;

#[derive(Serialize)]
pub struct Item {
  name: String,
  path: String,
}
